import json
from re import escape
from tkinter import N
import typing

from fastapi import Request, HTTPException
from starlette.responses import StreamingResponse, JSONResponse
from starlette.types import Message
from starlette.requests import Request as StarletteRequest  # 显式导入StarletteRequest

# 本地模块导入
from app.config.settings import settings
from app.core.encryption_utils import cipher
from app.core.local_logging import setup_logging

# 初始化日志记录器
logger = setup_logging()


def is_api_encrypted() -> bool:
    """
    判断当前API是否启用加密功能
    统一管理加密状态判断逻辑，提高可维护性
    Returns:
        bool: 加密启用状态（从配置中获取）
    """
    return settings.API_ENCRYPT


async def uniform_restful_response(request: Request, call_next) -> JSONResponse:
    """
    统一RESTful响应中间件（仅处理加解密逻辑，异常由全局中间件处理）
    """
    # 跳过文档路径（如Swagger UI）
    logger.debug(f"跳过文档路径检查: {request.url.path}")
    if request.url.path in settings.DOC_PATHS:
        return await call_next(request)

    
    if request.url.path in settings.AUTH_WHITELIST:
        return await call_next(request)

    # 阶段1：请求预处理（加密解密）
    processed_request = await process_encrypted_request(request)
    response = await call_next(processed_request)

    # 阶段2：响应处理（加密格式化）
    return await process_encrypted_response(response)


async def process_encrypted_request(request: Request) -> Request:
    """
    处理加密请求并重建请求对象
    主要逻辑：
    - 过滤非敏感请求方法（GET等）
    - 读取原始请求体
    - 根据加密配置解密请求体
    - 重建请求对象以保证协议一致性
    
    Args:
        request: 原始请求对象
        
    Returns:
        Request: 处理后的请求对象（可能包含解密后内容）
    """
    # 仅处理需要加密的请求方法
    if request.method not in ['POST', 'PUT', 'PATCH', 'GET']:
        return request

    # 读取原始请求体（可能加密）
    original_body = await request.body()
    if not original_body:  # 空请求体无需处理
        return request

    try:
        # 根据配置决定是否解密
        if is_api_encrypted():
            # 解密流程：Base64解码 -> RSA解密 -> 转UTF-8
            decrypted = cipher.decrypt(original_body.decode()).decode('utf-8')
        else:
            decrypted = original_body.decode()  # 未加密时直接解码
            
        # 转换为字节流（符合HTTP协议要求）
        modified_body = decrypted.encode('utf-8')
        
        # 重建请求对象（关键步骤：解决Content-Length不一致问题）
        new_request = await rebuild_request_object(request, modified_body)
        
        # 记录处理结果日志
        logger.debug(
            "[请求处理] 原始长度: %d | 解密后长度: %d",
            len(original_body), len(modified_body)
        )
        return new_request
    except (UnicodeDecodeError, ValueError) as e:
        logger.error(f"请求体解密失败: {str(e)}", exc_info=True)
        raise HTTPException(400, "无效的加密请求") from e


async def rebuild_request_object(request: Request, new_body: bytes) -> Request:
    """
    安全重建请求对象以保证协议一致性（不再处理content-length）
    """
    # 复制原始请求头（不修改content-length）
    headers = dict(request.headers)

    # 重建请求作用域（scope），保留原始头信息
    new_scope = request.scope.copy()
    new_scope["headers"] = [
        (k.lower().encode(), str(v).encode())  # 头信息统一小写并编码
        for k, v in headers.items()
    ]

    # 定义新的接收函数（用于FastAPI内部处理）
    async def new_receive() -> typing.Dict[str, typing.Any]:
        return {"type": "http.request", "body": new_body, "more_body": False}

    # 创建新的Starlette请求对象
    return StarletteRequest(new_scope, new_receive)


async def process_encrypted_response(response) -> typing.Union[StreamingResponse, JSONResponse]:
    """
    处理加密响应并标准化格式
    主要逻辑：
    - 保留流式响应（如文件下载）
    - 提取原始响应内容
    - 构建标准化加密响应
    
    Args:
        response: 原始响应对象
        
    Returns:
        Union[StreamingResponse, JSONResponse]: 处理后的响应对象
    """
    # 流式响应直接返回（不处理加密）
    if isinstance(response, StreamingResponse):
        return response

    try:
        # 提取原始响应内容（字符串形式）
        raw_content = await get_raw_content(response)
        if raw_content:
            logger.debug(f"[处理响应] [原始响应内容1]: {raw_content.encode()}...")  # 记录前100字符防敏感信息泄露
            return build_consistent_response(response, raw_content)
        else:
            logger.warning("响应内容为空")
            return format_error_response(500, "响应内容为空")
    except Exception as e:
        logger.error(f"响应内容提取失败: {str(e)}", exc_info=True)
        return format_error_response(500, "响应处理异常")


async def get_raw_content(response) -> str:
    """
    安全提取响应内容（兼容多种响应类型）
    支持类型：
    - JSONResponse（直接获取body）
    - 普通响应（获取body属性）
    - 流式响应（包括内部类 _StreamingResponse）
    """
    logger.debug(f"[处理响应] [原始响应类型] [get_raw_content] {type(response)}")  # 记录响应类型用于调试
    # 处理 JSONResponse
    if isinstance(response, JSONResponse):
        return response.body.decode()

    # 处理流式响应（包括内部类 _StreamingResponse）
    if hasattr(response, 'body_iterator'):  # 流式响应通用判断（包含 _StreamingResponse）
        content = []
        async for chunk in response.body_iterator:
            content.append(chunk)
        return b''.join(content).decode()

    # 处理普通响应（有 body 属性）
    if hasattr(response, 'body'):
        content = response.body
        return content.decode() if isinstance(content, bytes) else str(content)

    logger.warning("无法提取响应内容")
    return ''


def build_consistent_response(response, content: str) -> JSONResponse:
    """
    构建协议一致的加密响应（统一响应格式，避免嵌套错误）
    """
    try:
        # 根据加密配置处理数据
        if is_api_encrypted():
            encrypted_data = cipher.encrypt(content.encode('utf-8')).decode('utf-8')
        else:
            # 未加密时反序列化原始内容（可能包含业务错误信息）
            logger.debug(f"[处理响应] [原始响应内容2]: {content}")  # 记录前100字符防敏感信息泄露
            raw_data = json.loads(content)
            # 关键修改：如果原始内容包含业务错误，提取到外层
            logger.debug(f"[处理响应] [原始响应内容2]: {raw_data}")  # 记录前100字符防敏感信息泄露
            if (
                "code" in raw_data 
                # and raw_data["code"] >= 400
            ):
                return format_error_response(
                    status_code=raw_data["code"],
                    message=raw_data["message"]
                )
            
            encrypted_data = raw_data  # 业务成功时保留原始数据
            
        # 构建标准响应结构（外层code使用原始响应状态码）
        response_data = {
            "code": response.status_code,
            "message": "success" if response.status_code < 400 else "error",
            "data": encrypted_data
        }

        return JSONResponse(
            content=response_data,
            status_code=response.status_code
        )
    except json.JSONDecodeError as e:
        logger.error(f"响应内容反序列化失败: {str(e)}", exc_info=True)
        return format_error_response(500, "响应序列化失败")


def format_error_response(status_code: int, message: str) -> JSONResponse:
    """
    构建标准错误响应格式（修复字段访问错误）
    """
    response_data = {
        "code": status_code,
        "message": message,  # 直接使用传入的message字符串作为错误信息
        "data": None
    }
    return JSONResponse(
        status_code=status_code,
        content=response_data
    )
